<?php
namespace framework\library;

use ArrayAccess;

class Container implements ArrayAccess {

    // 当前容器的单例实例
    protected static $instance;

    // 同一进程下当前容器已存在的实例
    protected $instances = [];

    // 绑定类的别名
    protected $name = [];

    // 绑定
    protected $bind = [
        'app' => App::class,
        'request' => Request::class,
        'route' => Route::class,
        'dispatch' => Dispatch::class,
        'config' => Config::class,
        'middleware' => MiddleWare::class
    ];

    protected function __construct()
    {
        # 私有化构造
    }

    public static function getInstances()
    {
        if (!self::$instance) {
            self::$instance = new static;
        }

        return self::$instance;
    }

    public static function get($name)
    {
        return static::getInstances()->make($name);
    }

    public function make($abstract, $newInstance = false)
    {
        $abstract = $this->bind[$abstract] ?? null;
        if (!is_null($abstract)) {

            if(isset($this->instances[$abstract])) {
                return $this->instances[$abstract];
            }

            $reflect = new \ReflectionClass($abstract);
            if ($reflect->hasMethod('getInstance')) {
                $object = $abstract::getInstance();
            } else {
                $object = new $abstract;
            }

            if (!$newInstance) {
                $this->instances[$abstract] = $object;
            }

            return $object;
        }
    }

    public function bound($abstract)
    {
        $isBound = false;
        $abstract = $this->bind[$abstract] ?? null;
        is_null($abstract) || $isBound = $this->instances[$abstract] ? true : false;
        return $isBound;
    }

    public function offsetExists($offset)
    {
        return $this->bound($offset);
    }

    public function offsetGet($offset)
    {
        return $this->__get($offset);
    }

    public function offsetSet($offset, $value)
    {
        // TODO: Implement offsetSet() method.
    }

    public function offsetUnset($offset)
    {
        // TODO: Implement offsetUnset() method.
    }

    public function __get($name)
    {
        return $this->make($name);
    }

}


?>